package main

import "fmt"

func main() {
	// go语言中的函数不是原子操作，在底层是分为两步执行
	// 第一步: 返回值赋值
	// 第二步: 真正的RET返回
	// 函数中如果存在defer，那么defer执行的时机是在第一步和第二步之间
	// 一个函数可以有多个defer语句
	// 多用于函数释放之前释放资源
	fmt.Println("开始。")
	defer defers() // 最后加载 一般用于文件关闭防止内存泄露
	fmt.Println("结束。")
	defer fmt.Println("没了。")
}

func defers() {
	fmt.Println("defer执行。")
}

/// 下面常见面试题

func f1() int {
	x := 5
	defer func() {
		x++
	}()
	return x // 结果5
}

func f2() (x int) {
	defer func() {
		x++
	}()
	return 5 // 结果输出6
}
func f3() (y int) {
	x := 5
	defer func() {
		x++
	}()
	return x // 结果5
}
func f4() (y int) {
	x := 5
	defer func(x int) {
		x++ // 改变的是copy的值
	}(x)
	return 5 // 结果5
}

func f5() (x int) {
	defer func(x *int) {
		(*x)++ // 改变的是copy的值
	}(&x)
	return 5 // 结果6   => return 返回值 defer执行取x地址x++ 变为6
}

// 经典面试题

func f6(index string, a, b, int) int {
	ret := a + b
	fmt.Println(index, a, b, ret)
	return ret
}

func f7() {
	a := 1
	b := 2
	defer f6("1", a, f6("10", a, b))
	a = 0
	defer f6("2", a, f6("20", a, b))
	b = 1
}

// 1. a:=1
// 2. b:-2
// 3. defer calc("1"，1, calc("10"，1，2))
// 4. calc("10"，1, 2) // “10" 1 2 3
// 5. defer calc("1", 1, 3)
// 6.a 0
// 7. defer calc("2", @, calc("20", 0, 2))
// 8. calc("20", , 2) // "2e" e 2 2
// 9. defer calc("2", 0, 2)
// 10. b  1
// calc("2",0, 2) // "2" @ 2 2// calc("1"，1,3) //"1”1 3 4
